package main

import (
	_"errors"
	"fmt"
	_ "strconv"
)

// error 嵌套
type MyError struct {
	err error
	msg string
}

func (e *MyError) Error() string {
	return e.err.Error() + e.msg
}

type commonError struct {
	errorCode int
	errorMsg  string
}

func (ce *commonError) Error() string {
	return ce.errorMsg
}

func main() {
	// i,err:=strconv.Atoi("a")
	// if err != nil{
	// 	fmt.Println(err)
	// } else {
	// 	fmt.Println(i)
	// }

	// sum, err := add(-1, 2)
	// if err != nil {
	// 	newErr := MyError{err, "数据上传问题"}
	// 	fmt.Println(newErr)
	// } else {
	// 	fmt.Println(sum)
	// }

	// if cm, ok := err.(*commonError); ok {
	// 	fmt.Println("错误代码为:", cm.errorCode, "，错误信息为：", cm.errorMsg)
	// } else {
	// 	fmt.Println(sum)
	// }

	// e := errors.New("原始错误e") // Error Wrapping
	// w := fmt.Errorf("Wrap了一个错误:%w", e)
	// fmt.Println(w)
	// fmt.Println(errors.Unwrap(w)) // Unwrap 获取被嵌套error
	// fmt.Println(errors.Is(w,e))// 判断2个error是否是同一个
	// sum, err := add(5, 2)
	// var cm *commonError
	// if errors.As(err,&cm){
	// 	fmt.Println("错误代码为:",cm.errorCode,"，错误信息为：",cm.errorMsg)
	// } else{
	// 	fmt.Println(sum)
	// }

	/*
	defer 语句常被用于成对的操作，如文件的打开和关闭，加锁和释放锁，
	连接的建立和断开等。不管多么复杂的操作，都可以保证资源被正确地释放
	*/
	
	moreDefer()

	defer func(){
		if p:=recover();p!=nil{ //  recover 函数恢复 panic 异常
			fmt.Println(p)
		}
	}()
	connectMySQL("","lt","lo122")

	
}

func add(a, b int) (int, error) {
	if a < 0 || b < 0 {
		// return 0, errors.New("a或者b不能为负数")
		return 0, &commonError{ // 自定义error
			errorCode: 1,
			errorMsg:  "a或者b不能为负数"}
	} else {
		return a + b, nil
	}
}

func connectMySQL(ip,username,password string){
	if ip ==""{
		panic("ip不能为空") // 抛出 panic 终止程序的运行
		/*
		panic 异常是一种非常严重的情况，会让程序中断运行，使程序崩溃，
		所以如果是不影响程序运行的错误，不要使用 panic，使用普通错误 error 即可
		*/
	}
}

func moreDefer(){ // 多个defer执行顺序依照后进先出的原则
	defer  fmt.Println("First defer")
	defer  fmt.Println("Second defer")
	defer  fmt.Println("Three defer")
	fmt.Println("函数自身代码")
 }
 
